package untils

import (
	"context"
	"fmt"
	"time"
)

// RetryConfig 重试配置
type RetryConfig struct {
	MaxAttempts int           // 最大重试次数
	Delay       time.Duration // 重试延迟
	Backoff     float64       // 退避系数
}

// DefaultRetryConfig 默认重试配置
var DefaultRetryConfig = RetryConfig{
	MaxAttempts: 3,
	Delay:       1 * time.Second,
	Backoff:     2.0,
}

// RetryWithBackoff 带退避的重试机制
func RetryWithBackoff(ctx context.Context, config RetryConfig, operation func() error) error {
	var lastErr error

	for attempt := 1; attempt <= config.MaxAttempts; attempt++ {
		select {
		case <-ctx.Done():
			return ctx.Err()
		default:
		}

		err := operation()
		if err == nil {
			return nil
		}

		lastErr = err

		if attempt < config.MaxAttempts {
			delay := time.Duration(float64(config.Delay) * float64(attempt) * config.Backoff)
			select {
			case <-ctx.Done():
				return ctx.Err()
			case <-time.After(delay):
			}
		}
	}

	return fmt.Errorf("操作失败，已重试 %d 次，最后错误: %v", config.MaxAttempts, lastErr)
}

// RetryWithTimeout 带超时的重试机制
func RetryWithTimeout(ctx context.Context, timeout time.Duration, config RetryConfig, operation func() error) error {
	ctx, cancel := context.WithTimeout(ctx, timeout)
	defer cancel()

	return RetryWithBackoff(ctx, config, operation)
}

// ExponentialBackoff 指数退避重试
func ExponentialBackoff(ctx context.Context, maxAttempts int, baseDelay time.Duration, operation func() error) error {
	config := RetryConfig{
		MaxAttempts: maxAttempts,
		Delay:       baseDelay,
		Backoff:     2.0,
	}

	return RetryWithBackoff(ctx, config, operation)
}
